//
//  DMHashABSplitter.m
//  DualMediationSDK
//
//  Created by DualMediation on 2024/01/04.
//  Copyright © 2024 DualMediation. All rights reserved.
//

#import "DMHashABSplitter.h"
#import <CommonCrypto/CommonDigest.h>

// 错误域定义
static NSString * const DMHashABSplitterErrorDomain = @"DMHashABSplitterErrorDomain";

// 错误码定义
typedef NS_ENUM(NSInteger, DMHashABSplitterErrorCode) {
    DMHashABSplitterErrorCodeInvalidUniqueId = 1001,      // 无效的唯一标识
    DMHashABSplitterErrorCodeInvalidGroupRatios = 1002,   // 无效的分组比例
    DMHashABSplitterErrorCodeRatioSumNotHundred = 1003,   // 分组比例之和不等于100
    DMHashABSplitterErrorCodeNegativeRatio = 1004         // 分组比例包含负数
};

@implementation DMHashABSplitter

#pragma mark - Public Methods

+ (NSInteger)splitWithUniqueId:(NSString *)uniqueId 
                   groupRatios:(NSArray<NSNumber *> *)groupRatios 
                         error:(NSError **)error {
    
    // 参数验证
    if (![self validateUniqueId:uniqueId error:error]) {
        return -1;
    }
    
    if (![self validateGroupRatios:groupRatios error:error]) {
        return -1;
    }
    
    // 计算哈希值
    NSInteger hashValue = [self hashForString:uniqueId];
    
    // 取绝对值并模100，得到0-99范围内的数值
    NSInteger normalizedHash = labs(hashValue) % 100;
    
    // 根据分组比例确定分组
    NSInteger cumulativeRatio = 0;
    for (NSInteger i = 0; i < groupRatios.count; i++) {
        cumulativeRatio += [groupRatios[i] integerValue];
        if (normalizedHash < cumulativeRatio) {
            return i;
        }
    }
    
    // 默认返回最后一个组（理论上不会走到这里）
    return groupRatios.count - 1;
}

+ (NSInteger)splitWithUserId:(NSString *)userId 
                  sceneName:(NSString *)sceneName 
                groupRatios:(NSArray<NSNumber *> *)groupRatios 
                      error:(NSError **)error {
    
    // 参数验证
    if (!userId || userId.length == 0) {
        if (error) {
            *error = [NSError errorWithDomain:DMHashABSplitterErrorDomain
                                         code:DMHashABSplitterErrorCodeInvalidUniqueId
                                     userInfo:@{NSLocalizedDescriptionKey: @"用户ID不能为空"}];
        }
        return -1;
    }
    
    if (!sceneName || sceneName.length == 0) {
        if (error) {
            *error = [NSError errorWithDomain:DMHashABSplitterErrorDomain
                                         code:DMHashABSplitterErrorCodeInvalidUniqueId
                                     userInfo:@{NSLocalizedDescriptionKey: @"场景名称不能为空"}];
        }
        return -1;
    }
    
    // 组合用户ID和场景名称
    NSString *uniqueId = [NSString stringWithFormat:@"%@_%@", userId, sceneName];
    
    return [self splitWithUniqueId:uniqueId groupRatios:groupRatios error:error];
}

#pragma mark - Private Methods

/**
 * 验证唯一标识参数
 */
+ (BOOL)validateUniqueId:(NSString *)uniqueId error:(NSError **)error {
    if (!uniqueId || uniqueId.length == 0) {
        if (error) {
            *error = [NSError errorWithDomain:DMHashABSplitterErrorDomain
                                         code:DMHashABSplitterErrorCodeInvalidUniqueId
                                     userInfo:@{NSLocalizedDescriptionKey: @"唯一标识不能为空"}];
        }
        return NO;
    }
    return YES;
}

/**
 * 验证分组比例参数
 */
+ (BOOL)validateGroupRatios:(NSArray<NSNumber *> *)groupRatios error:(NSError **)error {
    if (!groupRatios || groupRatios.count == 0) {
        if (error) {
            *error = [NSError errorWithDomain:DMHashABSplitterErrorDomain
                                         code:DMHashABSplitterErrorCodeInvalidGroupRatios
                                     userInfo:@{NSLocalizedDescriptionKey: @"分组比例数组不能为空"}];
        }
        return NO;
    }
    
    NSInteger totalRatio = 0;
    for (NSNumber *ratio in groupRatios) {
        NSInteger ratioValue = [ratio integerValue];
        
        // 检查是否有负数
        if (ratioValue < 0) {
            if (error) {
                *error = [NSError errorWithDomain:DMHashABSplitterErrorDomain
                                             code:DMHashABSplitterErrorCodeNegativeRatio
                                         userInfo:@{NSLocalizedDescriptionKey: @"分组比例不能为负数"}];
            }
            return NO;
        }
        
        totalRatio += ratioValue;
    }
    
    // 检查比例之和是否等于100
    if (totalRatio != 100) {
        if (error) {
            NSString *errorMessage = [NSString stringWithFormat:@"分组比例之和必须为100，当前为%ld", (long)totalRatio];
            *error = [NSError errorWithDomain:DMHashABSplitterErrorDomain
                                         code:DMHashABSplitterErrorCodeRatioSumNotHundred
                                     userInfo:@{NSLocalizedDescriptionKey: errorMessage}];
        }
        return NO;
    }
    
    return YES;
}

/**
 * 使用MD5哈希算法生成整数值
 *
 * @param input 输入字符串
 * @return MD5哈希计算后的整数值
 */
+ (NSInteger)hashForString:(NSString *)input {
    // 将字符串转换为UTF-8编码的数据
    NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding];
    
    // 创建MD5哈希
    unsigned char digest[CC_MD5_DIGEST_LENGTH];
    CC_MD5(data.bytes, (CC_LONG)data.length, digest);
    
    // 将字节数组转换为整数值
    NSInteger hashValue = 0;
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        hashValue = hashValue * 256 + digest[i];
    }
    
    return hashValue;
}

@end